package mysql

import (
	"errors"
	"fmt"
	"gitee.com/lipore/plume/db_gorm/gen/code"
	"gitee.com/lipore/plume/db_gorm/gen/spec"
	"github.com/fatih/camelcase"
	"strings"
)

type ColumnInfo struct {
	Criteria string
	Param    []string
}

func renderQueryStmt(s spec.MethodSpec, q spec.QuerySpec) (string, error) {
	if len(q.Predicates) == 0 {
		return "", nil
	}
	operator := q.Operator
	criteriaItems := make([]string, len(q.Predicates))
	params := make([]string, 0)
	for i, predicate := range q.Predicates {
		columnName := fieldToColumn(predicate.FieldReference.ReferencedField())
		criteriaItem, err := comparatorToCriteria(predicate.Comparator, columnName)
		if err != nil {
			return "", err
		}
		criteriaItems[i] = criteriaItem
		if predicate.Comparator.NumberOfArguments() > 0 {
			for i := 0; i < predicate.Comparator.NumberOfArguments(); i++ {
				params = append(params, s.Params[predicate.ParamIndex+i].Name)
			}
		}
	}
	criteria := strings.Join(criteriaItems, string(operator))
	if len(params) == 0 {
		return fmt.Sprintf(".Where(\"%s\")", criteria), nil
	}

	return fmt.Sprintf(".Where(\"%s\", %s)", criteria, strings.Join(params, ",")), nil
}

func fieldToColumn(field code.StructField) string {
	fieldToken := camelcase.Split(field.Name)
	columnToken := make([]string, len(fieldToken))
	for i, t := range fieldToken {
		columnToken[i] = strings.ToLower(t)
	}
	return strings.Join(columnToken, "_")
}

func comparatorToCriteria(comparator spec.Comparator, columnName string) (string, error) {
	var criteria string
	switch comparator {
	case spec.ComparatorNot:
		criteria = fmt.Sprintf(" %s <> ? ", columnName)
	case spec.ComparatorEqual:
		criteria = fmt.Sprintf(" %s = ? ", columnName)
	case spec.ComparatorLessThan:
		criteria = fmt.Sprintf(" %s < ? ", columnName)
	case spec.ComparatorLessThanEqual:
		criteria = fmt.Sprintf(" %s <= ? ", columnName)
	case spec.ComparatorGreaterThan:
		criteria = fmt.Sprintf(" %s > ? ", columnName)
	case spec.ComparatorGreaterThanEqual:
		criteria = fmt.Sprintf(" %s >= ? ", columnName)
	case spec.ComparatorBetween:
		criteria = fmt.Sprintf(" %s BETWEEN ? AND ? ", columnName)
	case spec.ComparatorIn:
		criteria = fmt.Sprintf(" %s IN ? ", columnName)
	case spec.ComparatorNotIn:
		criteria = fmt.Sprintf(" %s NOT IN ? ", columnName)
	case spec.ComparatorTrue:
		criteria = fmt.Sprintf(" %s IS TRUE ", columnName)
	case spec.ComparatorFalse:
		criteria = fmt.Sprintf(" %s IS FALSE ", columnName)
	default:
		return "", errors.New("unsupported Comparator")
	}
	return criteria, nil
}
